using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Timing;
using Volo.Abp.Caching;
using System.Text.Json;
using Matrix.Notification.Channels;

namespace Matrix.Notification.Services
{
    /// <summary>
    /// 默认渠道配置服务实现
    /// </summary>
    public class DefaultChannelConfigurationService : IChannelConfigurationService, ITransientDependency
    {
        private readonly ILogger<DefaultChannelConfigurationService> _logger;
        private readonly IClock _clock;
        private readonly IDistributedCache _cache;
        private readonly ChannelConfigurationOptions _options;
        private readonly IEnumerable<INotificationChannel> _channels;

        public DefaultChannelConfigurationService(
            ILogger<DefaultChannelConfigurationService> logger,
            IClock clock,
            IDistributedCache cache,
            IOptions<ChannelConfigurationOptions> options,
            IEnumerable<INotificationChannel> channels)
        {
            _logger = logger;
            _clock = clock;
            _cache = cache;
            _options = options.Value;
            _channels = channels;
        }

        public async Task<ChannelConfiguration?> GetConfigurationAsync(
            NotificationChannel channel,
            CancellationToken cancellationToken = default)
        {
            try
            {
                var cacheKey = $"channel_configuration:{channel}";
                var cached = await _cache.GetStringAsync(cacheKey, cancellationToken);

                if (!string.IsNullOrEmpty(cached))
                {
                    return JsonSerializer.Deserialize<ChannelConfiguration>(cached);
                }

                var configuration = await LoadConfigurationFromStorageAsync(channel, cancellationToken);

                if (configuration != null)
                {
                    await _cache.SetStringAsync(
                        cacheKey,
                        JsonSerializer.Serialize(configuration),
                        new DistributedCacheEntryOptions
                        {
                            AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(10)
                        },
                        cancellationToken);
                }

                return configuration;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取渠道配置失败: Channel={Channel}", channel);
                return null;
            }
        }

        public async Task<List<ChannelConfiguration>> GetAllConfigurationsAsync(
            CancellationToken cancellationToken = default)
        {
            try
            {
                var configurations = new List<ChannelConfiguration>();

                foreach (NotificationChannel channel in Enum.GetValues<NotificationChannel>())
                {
                    var config = await GetConfigurationAsync(channel, cancellationToken);
                    if (config != null)
                    {
                        configurations.Add(config);
                    }
                }

                return configurations.OrderBy(c => c.Channel).ToList();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取所有渠道配置失败");
                return new List<ChannelConfiguration>();
            }
        }

        public async Task<ChannelConfigurationUpdateResult> UpdateConfigurationAsync(
            NotificationChannel channel,
            ChannelConfiguration configuration,
            CancellationToken cancellationToken = default)
        {
            try
            {
                _logger.LogInformation("开始更新渠道配置: Channel={Channel}", channel);

                var result = new ChannelConfigurationUpdateResult
                {
                    UpdatedTime = _clock.Now
                };

                // 验证配置
                var validationErrors = await ValidateConfigurationAsync(channel, configuration);
                if (validationErrors.Any())
                {
                    result.Success = false;
                    result.ErrorMessage = "配置验证失败";
                    result.ValidationErrors = validationErrors;
                    return result;
                }

                // 更新配置
                configuration.LastUpdatedTime = _clock.Now;
                configuration.Version++;

                await SaveConfigurationToStorageAsync(channel, configuration, cancellationToken);

                // 清除缓存
                var cacheKey = $"channel_configuration:{channel}";
                await _cache.RemoveAsync(cacheKey, cancellationToken);

                result.Success = true;
                result.Configuration = configuration;

                _logger.LogInformation("渠道配置更新成功: Channel={Channel}, Version={Version}",
                    channel, configuration.Version);

                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "更新渠道配置失败: Channel={Channel}", channel);

                return new ChannelConfigurationUpdateResult
                {
                    Success = false,
                    ErrorMessage = ex.Message,
                    UpdatedTime = _clock.Now
                };
            }
        }

        public async Task<bool> SetChannelEnabledAsync(
            NotificationChannel channel,
            bool enabled,
            CancellationToken cancellationToken = default)
        {
            try
            {
                var configuration = await GetConfigurationAsync(channel, cancellationToken);
                if (configuration == null)
                {
                    configuration = CreateDefaultConfiguration(channel);
                }

                configuration.IsEnabled = enabled;
                configuration.LastUpdatedTime = _clock.Now;

                await UpdateConfigurationAsync(channel, configuration, cancellationToken);

                _logger.LogInformation("渠道启用状态更新: Channel={Channel}, Enabled={Enabled}",
                    channel, enabled);

                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "更新渠道启用状态失败: Channel={Channel}, Enabled={Enabled}",
                    channel, enabled);
                return false;
            }
        }

        public async Task<ChannelTestResult> TestChannelAsync(
            NotificationChannel channel,
            CancellationToken cancellationToken = default)
        {
            var testResult = new ChannelTestResult
            {
                TestTime = _clock.Now,
                TestType = ChannelTestType.Connection
            };

            try
            {
                _logger.LogInformation("开始测试渠道连接: Channel={Channel}", channel);

                var configuration = await GetConfigurationAsync(channel, cancellationToken);
                if (configuration == null)
                {
                    testResult.Success = false;
                    testResult.ErrorMessage = "渠道配置不存在";
                    return testResult;
                }

                var startTime = _clock.Now;

                // 执行连接测试
                var notificationChannel = _channels.FirstOrDefault(c =>
                    Enum.TryParse<NotificationChannel>(c.ChannelType, out var channelType) && channelType == channel);

                if (notificationChannel == null)
                {
                    testResult.Success = false;
                    testResult.ErrorMessage = "渠道实现不存在";
                    return testResult;
                }

                var isAvailable = await notificationChannel.IsAvailableAsync(cancellationToken);
                testResult.ResponseTimeMs = (long)(_clock.Now - startTime).TotalMilliseconds;

                if (isAvailable)
                {
                    testResult.Success = true;
                    testResult.Message = "渠道连接测试成功";
                    configuration.TestStatus = ConnectionTestStatus.Success;
                }
                else
                {
                    testResult.Success = false;
                    testResult.ErrorMessage = "渠道不可用";
                    configuration.TestStatus = ConnectionTestStatus.Failed;
                }

                configuration.LastTestTime = _clock.Now;
                configuration.LastTestResult = testResult.Message;

                await UpdateConfigurationAsync(channel, configuration, cancellationToken);

                _logger.LogInformation("渠道连接测试完成: Channel={Channel}, Success={Success}, Duration={Duration}ms",
                    channel, testResult.Success, testResult.ResponseTimeMs);

                return testResult;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "渠道连接测试异常: Channel={Channel}", channel);

                testResult.Success = false;
                testResult.ErrorMessage = ex.Message;
                testResult.Exception = ex;
                testResult.ResponseTimeMs = (long)(_clock.Now - testResult.TestTime).TotalMilliseconds;

                return testResult;
            }
        }

        public async Task<ChannelStatistics> GetChannelStatisticsAsync(
            NotificationChannel channel,
            DateTime? startTime = null,
            DateTime? endTime = null,
            CancellationToken cancellationToken = default)
        {
            try
            {
                var cacheKey = $"channel_statistics:{channel}:{startTime?.Date:yyyy-MM-dd}:{endTime?.Date:yyyy-MM-dd}";
                var cached = await _cache.GetStringAsync(cacheKey, cancellationToken);

                if (!string.IsNullOrEmpty(cached))
                {
                    return JsonSerializer.Deserialize<ChannelStatistics>(cached)!;
                }

                var statistics = await GenerateStatisticsAsync(channel, startTime, endTime, cancellationToken);

                // 缓存统计结果5分钟
                await _cache.SetStringAsync(
                    cacheKey,
                    JsonSerializer.Serialize(statistics),
                    new DistributedCacheEntryOptions
                    {
                        AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5)
                    },
                    cancellationToken);

                return statistics;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取渠道统计信息失败: Channel={Channel}", channel);

                return new ChannelStatistics
                {
                    Channel = channel,
                    Period = new StatisticsPeriod
                    {
                        StartTime = startTime ?? _clock.Now.AddDays(-7),
                        EndTime = endTime ?? _clock.Now
                    },
                    LastUpdatedTime = _clock.Now
                };
            }
        }

        public async Task<bool> ResetToDefaultAsync(
            NotificationChannel channel,
            CancellationToken cancellationToken = default)
        {
            try
            {
                _logger.LogInformation("重置渠道配置为默认值: Channel={Channel}", channel);

                var defaultConfiguration = CreateDefaultConfiguration(channel);
                var result = await UpdateConfigurationAsync(channel, defaultConfiguration, cancellationToken);

                return result.Success;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "重置渠道配置失败: Channel={Channel}", channel);
                return false;
            }
        }

        public async Task<ChannelConfigurationExport> ExportConfigurationsAsync(
            IEnumerable<NotificationChannel>? channels = null,
            CancellationToken cancellationToken = default)
        {
            try
            {
                var targetChannels = channels?.ToList() ?? Enum.GetValues<NotificationChannel>().ToList();
                var exportData = new ChannelConfigurationExport
                {
                    ExportTime = _clock.Now,
                    Description = $"导出 {targetChannels.Count} 个渠道的配置"
                };

                foreach (var channel in targetChannels)
                {
                    var configuration = await GetConfigurationAsync(channel, cancellationToken);
                    if (configuration != null)
                    {
                        exportData.Configurations.Add(configuration);
                    }
                }

                exportData.Metadata["TotalConfigurations"] = exportData.Configurations.Count;
                exportData.Metadata["ExportedBy"] = "Matrix.Notification";

                _logger.LogInformation("渠道配置导出完成: Count={Count}", exportData.Configurations.Count);

                return exportData;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "导出渠道配置失败");
                throw;
            }
        }

        public async Task<ChannelConfigurationImportResult> ImportConfigurationsAsync(
            ChannelConfigurationExport exportData,
            bool overwriteExisting = false,
            CancellationToken cancellationToken = default)
        {
            try
            {
                _logger.LogInformation("开始导入渠道配置: Count={Count}, Overwrite={Overwrite}",
                    exportData.Configurations.Count, overwriteExisting);

                var importResult = new ChannelConfigurationImportResult
                {
                    ImportTime = _clock.Now,
                    TotalConfigurations = exportData.Configurations.Count
                };

                foreach (var configuration in exportData.Configurations)
                {
                    var detail = new ImportResultDetail
                    {
                        Channel = configuration.Channel
                    };

                    try
                    {
                        var existingConfig = await GetConfigurationAsync(configuration.Channel, cancellationToken);

                        if (existingConfig != null && !overwriteExisting)
                        {
                            detail.Status = ImportStatus.Skipped;
                            detail.Message = "配置已存在，未覆盖";
                            importResult.SkippedCount++;
                        }
                        else
                        {
                            if (existingConfig != null)
                            {
                                configuration.Version = existingConfig.Version + 1;
                                detail.Status = ImportStatus.Updated;
                                detail.Message = "更新现有配置";
                            }
                            else
                            {
                                configuration.Version = 1;
                                detail.Status = ImportStatus.Imported;
                                detail.Message = "导入新配置";
                            }

                            var updateResult = await UpdateConfigurationAsync(configuration.Channel, configuration, cancellationToken);

                            if (updateResult.Success)
                            {
                                importResult.SuccessCount++;
                            }
                            else
                            {
                                detail.Status = ImportStatus.Failed;
                                detail.ErrorMessage = updateResult.ErrorMessage;
                                importResult.FailureCount++;
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        detail.Status = ImportStatus.Failed;
                        detail.ErrorMessage = ex.Message;
                        importResult.FailureCount++;

                        _logger.LogWarning(ex, "导入渠道配置失败: Channel={Channel}", configuration.Channel);
                    }

                    importResult.Details.Add(detail);
                }

                importResult.Success = importResult.FailureCount == 0;

                _logger.LogInformation(
                    "渠道配置导入完成: Total={Total}, Success={Success}, Failed={Failed}, Skipped={Skipped}",
                    importResult.TotalConfigurations, importResult.SuccessCount, importResult.FailureCount, importResult.SkippedCount);

                return importResult;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "导入渠道配置失败");
                return new ChannelConfigurationImportResult
                {
                    Success = false,
                    ErrorMessage = ex.Message,
                    ImportTime = _clock.Now
                };
            }
        }

        #region 私有方法

        private async Task<ChannelConfiguration?> LoadConfigurationFromStorageAsync(
            NotificationChannel channel,
            CancellationToken cancellationToken)
        {
            try
            {
                // 这里应该从数据库或配置存储中加载配置
                // 目前返回默认配置用于演示
                return CreateDefaultConfiguration(channel);
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "从存储加载渠道配置失败: Channel={Channel}", channel);
                return null;
            }
        }

        private async Task SaveConfigurationToStorageAsync(
            NotificationChannel channel,
            ChannelConfiguration configuration,
            CancellationToken cancellationToken)
        {
            try
            {
                // 这里应该将配置保存到数据库或配置存储中
                // 目前仅记录日志用于演示
                _logger.LogDebug("保存渠道配置到存储: Channel={Channel}, Version={Version}",
                    channel, configuration.Version);

                await Task.CompletedTask;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "保存渠道配置到存储失败: Channel={Channel}", channel);
                throw;
            }
        }

        private ChannelConfiguration CreateDefaultConfiguration(NotificationChannel channel)
        {
            var configuration = new ChannelConfiguration
            {
                Channel = channel,
                Name = GetChannelName(channel),
                Description = GetChannelDescription(channel),
                IsEnabled = true,
                CreatedTime = _clock.Now,
                LastUpdatedTime = _clock.Now,
                Version = 1,
                IsDefault = true,
                TestStatus = ConnectionTestStatus.NotTested
            };

            // 根据渠道类型设置默认配置
            switch (channel)
            {
                case NotificationChannel.Email:
                    configuration.Settings = new Dictionary<string, object>
                    {
                        ["SmtpHost"] = "",
                        ["SmtpPort"] = 587,
                        ["UseSsl"] = true,
                        ["UserName"] = "",
                        ["Password"] = "",
                        ["FromEmail"] = "",
                        ["FromName"] = "Matrix.Notification"
                    };
                    break;

                case NotificationChannel.Push:
                    configuration.Settings = new Dictionary<string, object>
                    {
                        ["FCMServerKey"] = "",
                        ["FCMSenderId"] = "",
                        ["APNSKeyId"] = "",
                        ["APNSTeamId"] = "",
                        ["APNSBundleId"] = "",
                        ["HMSAppId"] = "",
                        ["HMSAppSecret"] = ""
                    };
                    break;

                case NotificationChannel.WebHook:
                    configuration.Settings = new Dictionary<string, object>
                    {
                        ["DefaultUrl"] = "",
                        ["TimeoutSeconds"] = 30,
                        ["RetryCount"] = 3,
                        ["SigningSecret"] = ""
                    };
                    break;

                case NotificationChannel.SMS:
                    configuration.Settings = new Dictionary<string, object>
                    {
                        ["Provider"] = "",
                        ["ApiKey"] = "",
                        ["ApiSecret"] = "",
                        ["FromNumber"] = ""
                    };
                    break;
            }

            return configuration;
        }

        private async Task<List<ConfigurationValidationError>> ValidateConfigurationAsync(
            NotificationChannel channel,
            ChannelConfiguration configuration)
        {
            var errors = new List<ConfigurationValidationError>();

            // 基础验证
            if (string.IsNullOrWhiteSpace(configuration.Name))
            {
                errors.Add(new ConfigurationValidationError
                {
                    Field = "Name",
                    Message = "配置名称不能为空",
                    ErrorCode = "REQUIRED_FIELD",
                    Severity = ValidationSeverity.Error
                });
            }

            // 渠道特定验证
            switch (channel)
            {
                case NotificationChannel.Email:
                    ValidateEmailConfiguration(configuration, errors);
                    break;
                case NotificationChannel.Push:
                    ValidatePushConfiguration(configuration, errors);
                    break;
                case NotificationChannel.WebHook:
                    ValidateWebHookConfiguration(configuration, errors);
                    break;
                case NotificationChannel.SMS:
                    ValidateSmsConfiguration(configuration, errors);
                    break;
            }

            return await Task.FromResult(errors);
        }

        private void ValidateEmailConfiguration(ChannelConfiguration configuration, List<ConfigurationValidationError> errors)
        {
            if (!configuration.Settings.TryGetValue("SmtpHost", out var host) ||
                string.IsNullOrWhiteSpace(host?.ToString()))
            {
                errors.Add(new ConfigurationValidationError
                {
                    Field = "Settings.SmtpHost",
                    Message = "SMTP主机地址不能为空",
                    ErrorCode = "REQUIRED_SMTP_HOST",
                    Severity = ValidationSeverity.Error
                });
            }

            if (!configuration.Settings.TryGetValue("FromEmail", out var fromEmail) ||
                string.IsNullOrWhiteSpace(fromEmail?.ToString()))
            {
                errors.Add(new ConfigurationValidationError
                {
                    Field = "Settings.FromEmail",
                    Message = "发件人邮箱不能为空",
                    ErrorCode = "REQUIRED_FROM_EMAIL",
                    Severity = ValidationSeverity.Error
                });
            }
        }

        private void ValidatePushConfiguration(ChannelConfiguration configuration, List<ConfigurationValidationError> errors)
        {
            var hasFcmConfig = configuration.Settings.ContainsKey("FCMServerKey") &&
                              !string.IsNullOrWhiteSpace(configuration.Settings["FCMServerKey"].ToString());
            var hasApnsConfig = configuration.Settings.ContainsKey("APNSKeyId") &&
                               !string.IsNullOrWhiteSpace(configuration.Settings["APNSKeyId"].ToString());
            var hasHmsConfig = configuration.Settings.ContainsKey("HMSAppId") &&
                              !string.IsNullOrWhiteSpace(configuration.Settings["HMSAppId"].ToString());

            if (!hasFcmConfig && !hasApnsConfig && !hasHmsConfig)
            {
                errors.Add(new ConfigurationValidationError
                {
                    Field = "Settings",
                    Message = "至少需要配置一个推送平台（FCM、APNS或HMS）",
                    ErrorCode = "REQUIRED_PUSH_PLATFORM",
                    Severity = ValidationSeverity.Error
                });
            }
        }

        private void ValidateWebHookConfiguration(ChannelConfiguration configuration, List<ConfigurationValidationError> errors)
        {
            if (!configuration.Settings.TryGetValue("DefaultUrl", out var url) ||
                string.IsNullOrWhiteSpace(url?.ToString()))
            {
                errors.Add(new ConfigurationValidationError
                {
                    Field = "Settings.DefaultUrl",
                    Message = "默认WebHook URL不能为空",
                    ErrorCode = "REQUIRED_WEBHOOK_URL",
                    Severity = ValidationSeverity.Error
                });
            }
        }

        private void ValidateSmsConfiguration(ChannelConfiguration configuration, List<ConfigurationValidationError> errors)
        {
            if (!configuration.Settings.TryGetValue("Provider", out var provider) ||
                string.IsNullOrWhiteSpace(provider?.ToString()))
            {
                errors.Add(new ConfigurationValidationError
                {
                    Field = "Settings.Provider",
                    Message = "SMS提供商不能为空",
                    ErrorCode = "REQUIRED_SMS_PROVIDER",
                    Severity = ValidationSeverity.Error
                });
            }
        }

        private async Task<ChannelStatistics> GenerateStatisticsAsync(
            NotificationChannel channel,
            DateTime? startTime,
            DateTime? endTime,
            CancellationToken cancellationToken)
        {
            // 这里应该从实际的统计数据中生成
            // 目前返回模拟数据用于演示
            var random = new Random();

            var statistics = new ChannelStatistics
            {
                Channel = channel,
                Period = new StatisticsPeriod
                {
                    StartTime = startTime ?? _clock.Now.AddDays(-7),
                    EndTime = endTime ?? _clock.Now
                },
                TotalSent = random.Next(1000, 10000),
                SuccessCount = random.Next(800, 9000),
                AverageResponseTimeMs = random.Next(100, 2000),
                MaxResponseTimeMs = random.Next(5000, 30000),
                MinResponseTimeMs = random.Next(10, 100),
                LastUpdatedTime = _clock.Now
            };

            statistics.FailureCount = statistics.TotalSent - statistics.SuccessCount;

            // 按状态码分组
            statistics.StatusCodeBreakdown["200"] = statistics.SuccessCount;
            statistics.StatusCodeBreakdown["400"] = (long)(statistics.FailureCount * 0.3);
            statistics.StatusCodeBreakdown["500"] = (long)(statistics.FailureCount * 0.7);

            // 按小时分组
            for (int hour = 0; hour < 24; hour++)
            {
                statistics.HourlyBreakdown[hour] = new HourlyStatistics
                {
                    Hour = hour,
                    SentCount = random.Next(0, 500),
                    SuccessCount = random.Next(0, 450),
                    FailureCount = random.Next(0, 50)
                };
            }

            return await Task.FromResult(statistics);
        }

        private string GetChannelName(NotificationChannel channel)
        {
            return channel switch
            {
                NotificationChannel.Email => "邮件通知",
                NotificationChannel.Push => "推送通知",
                NotificationChannel.WebHook => "WebHook通知",
                NotificationChannel.SMS => "短信通知",
                _ => channel.ToString()
            };
        }

        private string GetChannelDescription(NotificationChannel channel)
        {
            return channel switch
            {
                NotificationChannel.Email => "基于SMTP协议的电子邮件通知",
                NotificationChannel.Push => "支持FCM、APNS、HMS的多平台推送通知",
                NotificationChannel.WebHook => "基于HTTP协议的WebHook回调通知",
                NotificationChannel.SMS => "支持多个提供商的短信通知",
                _ => $"{channel}通知渠道"
            };
        }

        #endregion
    }

    #region 配置选项

    /// <summary>
    /// 渠道配置选项
    /// </summary>
    public class ChannelConfigurationOptions
    {
        /// <summary>
        /// 配置存储模式
        /// </summary>
        public ConfigurationStorageMode StorageMode { get; set; } = ConfigurationStorageMode.Cache;

        /// <summary>
        /// 配置缓存过期时间（分钟）
        /// </summary>
        public int CacheExpirationMinutes { get; set; } = 10;

        /// <summary>
        /// 启用配置验证
        /// </summary>
        public bool EnableValidation { get; set; } = true;

        /// <summary>
        /// 启用配置历史
        /// </summary>
        public bool EnableHistory { get; set; } = true;

        /// <summary>
        /// 最大配置版本数
        /// </summary>
        public int MaxVersionCount { get; set; } = 10;
    }

    /// <summary>
    /// 配置存储模式
    /// </summary>
    public enum ConfigurationStorageMode
    {
        /// <summary>
        /// 仅缓存存储
        /// </summary>
        Cache,

        /// <summary>
        /// 数据库存储
        /// </summary>
        Database,

        /// <summary>
        /// 文件存储
        /// </summary>
        File,

        /// <summary>
        /// 配置中心存储
        /// </summary>
        ConfigurationCenter
    }

    #endregion
}